package icu.d4peng.basic.message.mail.service.impl;

import icu.d4peng.basic.message.mail.properties.MailProperties;
import icu.d4peng.basic.message.mail.service.MailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.Assert;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.standard.StandardDialect;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.FileTemplateResolver;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Map;
import java.util.Properties;

/**
 * MailServiceImpl:邮件服务实现
 *
 * @author d4peng <a href="d4peng@qq.com">d4peng@qq.com</a>
 * @since 2023.12.03
 */
public class MailServiceImpl implements MailService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MailServiceImpl.class);
    private final MailProperties mailProperties;
    private final JavaMailSender javaMailSender;
    private final MimeMessage mimeMessage;
    private final MimeMessageHelper mimeMessageHelper;
    private final TaskExecutor taskExecutor;
    private final TemplateEngine templateEngine;


    public MailServiceImpl(MailProperties mailProperties, TaskExecutor taskExecutor) {
        Assert.notNull(mailProperties, "mailProperties can't be null!");
        Assert.notNull(taskExecutor, "taskExecutor can't be null!");
        this.taskExecutor = taskExecutor;
        this.mailProperties = mailProperties;
        this.templateEngine = createTemplateEngine();
        this.javaMailSender = createJavaMailSender();
        this.mimeMessage = createMimeMessage();
        this.mimeMessageHelper = createMimeMessageHelper();
    }

    @Override
    public void sendTextEmail(String to, String subject, String context) {
        try {
            this.mimeMessageHelper.setTo(to);
            this.mimeMessageHelper.setSubject(subject);
            this.mimeMessageHelper.setText(context, false);
            this.mimeMessageHelper.setFrom(this.mailProperties.getUsername());
        } catch (MessagingException e) {
            LOGGER.error(e.getMessage());
        }
        this.taskExecutor.execute(() -> this.javaMailSender.send(this.mimeMessage));
    }

    @Override
    public void sendHtmlEmail(String to, String subject, String templateName, Map<String, Object> context) {
        try {
            this.mimeMessageHelper.setTo(to);
            this.mimeMessageHelper.setSubject(subject);
            this.mimeMessageHelper.setText(mapConvertTemplate(templateName, context), true);
            this.mimeMessageHelper.setFrom(this.mailProperties.getUsername());
        } catch (MessagingException e) {
            LOGGER.error(e.getMessage());
        }
        this.javaMailSender.send(this.mimeMessage);
        this.taskExecutor.execute(() -> this.javaMailSender.send(this.mimeMessage));
    }

    /**
     * map变成template里面属性
     *
     * @param templateName 模板名称
     * @param map          map里面的值
     * @return 解析HTML后的值
     */
    private String mapConvertTemplate(String templateName, Map<String, Object> map) {
        Context context = new Context();
        context.setVariables(map);
        return this.templateEngine.process(templateName, context);
    }

    public MimeMessageHelper createMimeMessageHelper() {
        try {
            return new MimeMessageHelper(this.mimeMessage, true, "UTF-8");
        } catch (MessagingException e) {
            LOGGER.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private MimeMessage createMimeMessage() {
        return this.javaMailSender.createMimeMessage();
    }


    private JavaMailSender createJavaMailSender() {
        JavaMailSenderImpl javaMailSenderImpl = new JavaMailSenderImpl();
        javaMailSenderImpl.setHost(this.mailProperties.getHost());
        if (this.mailProperties.getPort() != null) {
            javaMailSenderImpl.setPort(this.mailProperties.getPort());
        }
        javaMailSenderImpl.setUsername(this.mailProperties.getUsername());
        javaMailSenderImpl.setPassword(this.mailProperties.getPassword());
        javaMailSenderImpl.setProtocol(this.mailProperties.getProtocol());
        javaMailSenderImpl.setDefaultEncoding(this.mailProperties.getDefaultEncoding().name());
        if (!this.mailProperties.getProperties().isEmpty()) {
            Properties properties = new Properties();
            properties.putAll(this.mailProperties.getProperties());
            javaMailSenderImpl.setJavaMailProperties(properties);
        }
        if (this.mailProperties.isTestConnection()) {
            try {
                javaMailSenderImpl.testConnection();
            } catch (MessagingException e) {
                LOGGER.error(e.getMessage());
                throw new RuntimeException(e);
            }
        }
        return javaMailSenderImpl;
    }

    /**
     * 创建html模板解析
     *
     * @return 模板引擎
     */
    private TemplateEngine createTemplateEngine() {
        FileTemplateResolver fileTemplateResolver = new FileTemplateResolver();
        fileTemplateResolver.setPrefix(System.getProperties().getProperty("user.dir") + this.mailProperties.getTemplatePrefix());
        fileTemplateResolver.setSuffix(this.mailProperties.getTemplateSuffix());
        fileTemplateResolver.setTemplateMode(TemplateMode.HTML);
        fileTemplateResolver.setCacheable(true);

        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setDialect(new StandardDialect());
        templateEngine.setTemplateResolver(fileTemplateResolver);
        return templateEngine;
    }


}
